package com.link4a.doms.service;

import java.util.Date;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

import javax.annotation.PostConstruct;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

import org.apache.commons.lang3.CharEncoding;
import org.springframework.core.io.InputStreamSource;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Async;

/**
 * @author brown
 */
public class MailService {

	private AtomicReference<JavaMailSenderImpl> javaMailSenderReference = new AtomicReference<>();
	
	private static String DEFAULT_PROTOCOL = "smtp";
	private static String DEFAULT_ENCODING = CharEncoding.UTF_8;
//	private Properties JAVA_MAIL_PROPERTIES = new Properties();
	
	private String host;
	private String username;
	private String password;
	private String protocol;
	private String encoding;
	
	public MailService(String host, String username, String password) {
		this.host = host;
		this.username = username;
		this.password = password;
		
		this.protocol = DEFAULT_PROTOCOL;
		this.encoding = DEFAULT_ENCODING;
	}
	
	public MailService(String host, String username, String password, String protocol, String encoding) {
		this.host = host;
		this.username = username;
		this.password = password;
		this.protocol = protocol;
		this.encoding = encoding;
	}

	@PostConstruct
	public void init() {

		JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl();

		javaMailSender.setHost(this.host);
		javaMailSender.setUsername(this.username);
		javaMailSender.setPassword(this.password);
		
		javaMailSender.setProtocol(this.protocol);
		javaMailSender.setDefaultEncoding(this.encoding);
//		javaMailSender.setJavaMailProperties(JAVA_MAIL_PROPERTIES);

		javaMailSenderReference.set(javaMailSender);
	}

	@Async
	public void send(String to, String subject, String body) throws MessagingException {
		MimeMessage mimeMessage = buildMimeMessage(to, subject, body);
		javaMailSenderReference.get().send(mimeMessage);
	}
	
	@Async
	public void send(String to, String subject, String body, boolean multipart, Map<String, InputStreamSource> attachments) throws MessagingException {
		MimeMessage mimeMessage = buildMimeMessage(to, subject, body, multipart, attachments);
		javaMailSenderReference.get().send(mimeMessage);
	}

	public void sendImmediately(String to, String subject, String body) throws Exception {
		MimeMessage mimeMessage = buildMimeMessage(to, subject, body);
		javaMailSenderReference.get().send(mimeMessage);
	}
	
	public void sendImmediately(String to, String subject, String body, boolean multipart, Map<String, InputStreamSource> attachments) throws Exception {
		MimeMessage mimeMessage = buildMimeMessage(to, subject, body, multipart, attachments);
		javaMailSenderReference.get().send(mimeMessage);
	}
	
	private MimeMessage buildMimeMessage(String to, String subject, String body) throws MessagingException {
		return buildMimeMessage(to, subject, body, false, null);
	}

	private MimeMessage buildMimeMessage(String to, String subject, String body, boolean multipart, Map<String, InputStreamSource> attachments) throws MessagingException {

		MimeMessageHelper messageHelper = new MimeMessageHelper(javaMailSenderReference.get().createMimeMessage(), multipart);

		messageHelper.setFrom(javaMailSenderReference.get().getUsername());
		messageHelper.setTo(to);
		messageHelper.setSubject(subject);
		messageHelper.setText(body, true);
		messageHelper.setSentDate(new Date());

		if (multipart && attachments != null) {
			for (Map.Entry<String, InputStreamSource> attachment : attachments.entrySet()) {
				messageHelper.addAttachment(attachment.getKey(), attachment.getValue());
			}
		}
		return messageHelper.getMimeMessage();
	}
}
